package com.clp.inflxudb.core.domain;

import com.clp.inflxudb.core.enums.CompareOp;
import com.clp.inflxudb.core.enums.FluxKVType;
import com.clp.inflxudb.core.enums.LogicOp;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 结构：
 * o -rowLogicOp-> o -rowLogicOp-> o -> o - ...
 * |
 * colLogicOp
 * |
 * o - o - o - o - ...
 * |
 * colLogicOp
 * |
 * o - o - o - o - ...
 */
public class FluxKVGrouper {
    /**
     * 行逻辑连接符
     */
    private LogicOp rowLogicOp;
    /**
     * 列逻辑连接符
     */
    private LogicOp colLogicOp;

    /**
     * 二维的键值对矩阵
     */
    private List<List<FluxKV>> fluxKVsList;

    public FluxKVGrouper(LogicOp rowLogicOp, LogicOp colLogicOp) {
        this.rowLogicOp = rowLogicOp;
        this.colLogicOp = colLogicOp;
        fluxKVsList = new ArrayList<>();
    }

    /**
     * 默认的 ： 行用 or 连接， 列用 and 连接
     *
     * @return
     */
    public static FluxKVGrouper getDefaultInstance() {
        return new FluxKVGrouper(LogicOp.or, LogicOp.and);
    }

    /**
     * 直接添加FluxKV
     *
     * @param fluxKV
     * @return
     */
    public FluxKVGrouper addRow(FluxKV fluxKV) {
        fluxKVsList.add(Arrays.asList(fluxKV));
        return this;
    }

    /**
     * 添加单个键值对类型
     *
     * @param keyStr
     * @param valObj
     * @param compareOp
     * @param kvType
     * @return
     */
    public FluxKVGrouper addRow(String keyStr, Object valObj, CompareOp compareOp, FluxKVType kvType) {
        if (valObj instanceof List) {
            return addRow(keyStr, (List)valObj, compareOp, kvType);
        }
        fluxKVsList.add(Arrays.asList(new FluxKV(keyStr, valObj, compareOp, kvType)));
        return this;
    }

    /**
     * 添加单个键值对
     *
     * @param keyStr
     * @param valObj
     * @param kvType
     * @return
     */
    public FluxKVGrouper addRowEqual(String keyStr, Object valObj, FluxKVType kvType) {
        if (keyStr == null || valObj == null) {
            return this;
        }
        if (valObj instanceof List) {
            return addRowEqual(keyStr, (List)valObj, kvType);
        }
        return addRow(keyStr, valObj, CompareOp.EQUAL, kvType);
    }

    /**
     * 直接添加键值对列表
     *
     * @param fluxKVs
     * @return
     */
    public FluxKVGrouper addRow(List<FluxKV> fluxKVs) {
        fluxKVsList.add(fluxKVs);
        return this;
    }

    /**
     * 添加键值对列表
     *
     * @param compareOp
     * @param kvType
     * @return
     */
    public FluxKVGrouper addRow(String keyStr, List<Object> valObjs, CompareOp compareOp, FluxKVType kvType) {
        ArrayList<FluxKV> fluxKVs = new ArrayList<>();
        for (Object valObj : valObjs) {
            fluxKVs.add(new FluxKV(keyStr, valObj, compareOp, kvType));
        }
        return addRow(fluxKVs);
    }

    /**
     * 添加键值对
     *
     * @param kvType
     * @return
     */
    public FluxKVGrouper addRowEqual(String keyStr, List<Object> valObjs, FluxKVType kvType) {
        return addRow(keyStr, valObjs, CompareOp.EQUAL, kvType);
    }

    public FluxKVGroup group() {
        List<FluxKVGroup> colGroups = new ArrayList<>();
        FluxKVGroup tempGroup, finalGroup = null;
        for (List<FluxKV> fluxKVs : fluxKVsList) {
            if (fluxKVs.isEmpty()) {
                continue;
            }
            tempGroup = new FluxKVGroup(fluxKVs.get(0));
            for (int i = 1; i < fluxKVs.size(); i++) {
                tempGroup = tempGroup.conn(new FluxKVGroup(fluxKVs.get(i)), rowLogicOp);
            }
            colGroups.add(tempGroup);
        }
        if (!colGroups.isEmpty()) {
            finalGroup = colGroups.get(0);
            for (int i = 1; i < colGroups.size(); i++) {
                finalGroup = finalGroup.conn(colGroups.get(i), colLogicOp);
            }
        }
        return finalGroup;
    }
}
